/*
 * Copyright (C) 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** 
 * YouTube gadget.
 *
 * In edit mode, allows user to set size of video, the clip to watch and
 * possibly a new movieId.
 */

var DEFAULT_WIDTH = '425';
var DEFAULT_MOVIE_ID='ZSzOd__feIw';
var lastPlayerMovieId = null;

/**
 * Calculates an appropriate height for the given gadget width.
 */
function calculateHeight(width) {
  return (width * 9 / 16) + 25;
}

/**
 * Insert YouTube player SWF
 */
function insertSwf(movieId, width, height) {
  // Copy default values from prefs, if not already set in 
  //
  // Temp: insert movie here
  var params = { allowScriptAccess: "always" };
  var atts = { id: "ytplayer" };
  var url = "http://www.youtube.com/v/" + movieId + "?enablejsapi=1";
  swfobject.embedSWF(url, "playerdiv", width, height, "8", null, null, params, atts);
  lastPlayerMovieId = movieId;
}


/**
 * Callback on player ready.
 */
function onYouTubePlayerReady(playerId) {
  // Reset gadget height
  gadgets.window.adjustHeight();
}


/**
 * Gadget state change callback.
 */
function onStateUpdated() {
  // Handle startup gracefully
  if (!isGadgetReady()) {
    stateAvailable = true;
    checkGadgetReady();
    return;
  }
  // At this point mode is set and state is available

  // Retrieve width
  var width = parseInt(wave.getState().get('width', DEFAULT_WIDTH));
  if (isNaN(width)) {
    wave.log('invalid gadget width state value: ' + wave.getState().get('width'));
  }
  $('#width').val(width);
  var height = calculateHeight(width);

  // Retrieve movie
  var movieId = wave.getState().get('movieId', DEFAULT_MOVIE_ID);
  $('#movieId').val(movieId);

  var player = $('#ytplayer');
  if (player.size() == 0) {
    insertSwf(movieId, width, height);
  } else {
    if (movieId != lastPlayerMovieId) {
      player.get(0).cueVideoById(movieId, 0, 'default');
      lastPlayerMovieId = movieId;
    }
    player.width(width);
    player.height(height);
  }
  gadgets.window.adjustHeight();
}

/**
 * Gadget mode change callback.
 */
function onModeUpdated() {
  // Handle startup gracefully
  if (!isGadgetReady()) {
    modeAvailable = true;
    checkGadgetReady();
    return;
  }

  // At this point mode is set and state is available, though may not have been
  // applied to the gadget.

  var stuff = $('#stuff');
  var holder = $('#settingsholder');
  if (wave.getMode() == wave.Mode.EDIT && !stuff.hasClass('edit')) {
    stuff.addClass('edit');
    var pos = holder.offset();
    pos.top -= holder.height();
    holder.offset(pos);
    holder.animate({top: ('+=' + holder.height())}, 'slow');
  } else if (wave.getMode() != wave.Mode.EDIT && stuff.hasClass('edit')) {
    holder.animate({top: ('-=' + holder.height())}, 'slow', function() {
      stuff.removeClass('edit');
      holder.css('top', 0);
      gadgets.window.adjustHeight();
    });
  }
  gadgets.window.adjustHeight();
}


/**
 * Sets gadget state from UI elements.
 */
function updateState() {
  var movieId = $('#movieId').val();
  if (movieId != null && movieId != '') {
    wave.getState().submitValue('movieId', movieId);
  }
}


/** Validate the current value in the width input box. */
function isWidthValid() {
  return getWidth() != null;
}

function getWidth() {
  var strArray = ($('#width').val()).match(/^[0-9]+$/);
  if (strArray == null) {
    return null;
  }
  var val = parseInt(strArray[0]);
  if (val < 100 || val > 2000) {
    return null;
  }
  return val;
}

/** Validate the movie id input field. */
function isMovieIdValid() {
  return getMovieId() != null;
}

/** Fetches the movie id from the input field. */
function getMovieId() {
  var input = $('#movieId');
  var strArray = input.val().match('^(?:http(?:s)?://(?:www.)?youtube.com/watch[?#].*v=)?([^& ]+)');
  if (strArray.length != 2) {
    return null;
  }
  return strArray[1];
}


/**
 * Gadget initialisation functions.
 */

var libsLoaded = false;
var stateAvailable = false;
var modeAvailable = false;

function isGadgetReady() {
  return libsLoaded && stateAvailable && modeAvailable;
}

/**
 * To be called to check whether gadget is finally ready.
 *
 * Must only be called once.
 */
function checkGadgetReady() {
  if (!isGadgetReady()) {
    return;
  }

  // Set event handlers where required.
  $('#movieId').change(function() {
        var input = $(this);
        if (isMovieIdValid()) {
          input.removeClass('error');
          wave.getState().submitValue('movieId', getMovieId());
        } else {
          input.addClass('error');
        }
      });

  // Set event handlers where required.
  $('#width').change(function() {
        var input = $(this);
        if (isWidthValid()) {
          input.removeClass('error');
          wave.getState().submitValue('width', getWidth());
        } else {
          input.addClass('error');
        }
      });

  // Call handlers for mode and gadget state
  onModeUpdated();
  onStateUpdated();
}

gadgets.util.registerOnLoadHandler(function() {
      wave.setStateCallback(onStateUpdated);
      wave.setModeCallback(onModeUpdated);
    });

google.setOnLoadCallback(function() {
    libsLoaded = true;
    checkGadgetReady();
    });
